
#include "common.h"
#include "cache_dir.h"
#include "conf.h"

#define conf_debug(fmt, ...) fprintf(stdout, "[%s.%d %s] "fmt, \
				__FILE__, __LINE__, __func__, __VA_ARGS__);


void conf_parse(void)
{
#if USE_INI
	parse_ini_conf(conf->log.conf);
#else 
	parse_lua_conf(conf->log.conf);
#endif
}


void conf_default(void)
{
	/* default value of config->log */
	if(!conf) {
		conf = mempool_alloc(sizeof(*conf));
		assert(conf);
	}
	
	conf->log.error = strdup(DEFAULT_ERROR_LOG);
	conf->log.debug = strdup(DEFAULT_DEBUG_LOG);
	conf->log.warn = strdup(DEFAULT_WARN_LOG);
	conf->log.access = strdup(DEFAULT_ACCESS_LOG);

	conf->server.port = htons(DEFAULT_PORT);
	inet_pton(AF_INET, DEFAULT_BIND_ADDR4, &conf->server.bind_addr4);
	conf->server.debug_mode = DEFAULT_DEBUG_MODE;
	conf->server.debug_level = DEFAULT_DEBUG_LEVEL;
	conf->server.worker = DEFAULT_WORKER_NUMBER;
	conf->server.max_size_in_mem = DEFAULT_MAX_SIZE_IN_MEM;
	conf->server.max_size_in_shm = DEFAULT_MAX_SIZE_IN_SHM;
	conf->server.objects = DEFAULT_OBJECTS;
	conf->server.max_object_size_in_mem = DEFAULT_MAX_OBJECT_SIZE_IN_MEM;
	conf->server.maxfds = DEFAULT_MAXFDS;
	conf->server.daemon = 1;
	
	conf->timeout.client_life = DEFAULT_CLIENT_LIFE;
	conf->timeout.server_life = DEFAULT_SERVER_LIFE;
	conf->timeout.request = DEFAULT_REQUEST_TIMEOUT;
	conf->timeout.reply = DEFAULT_REPLY_TIMEOUT;
	conf->timeout.connect = DEFAULT_CONNECT_TIMEOUT;

	if(!conf->cache.dir) {
		conf->cache.dir = array_create();
		cache_dir_t *dentry = mempool_alloc(sizeof(*dentry));
		assert(dentry);
		dentry->path = strdup("/var/cache");
		dentry->max_size = 1>>30;
		dentry->no = 0;
		array_append(conf->cache.dir, dentry);
	}
}

void conf_reload(void) 
{
	conf_parse();
}

#if USE_INI
#define INI_KEY(x) ini_keys[x].key
enum KEY_ENUMS {
	SERVER_NONE = 0,
	SERVER_PORT,
	SERVER_BIND_ADDR4, 
	SERVER_MAX_SIZE_IN_SHM,
	SERVER_MAX_SIZE_IN_MEM,
	SERVER_WORKER,
	SERVER_OBJECTS,
	SERVER_DEBUG_MODE,
	SERVER_DEBUG_LEVEL,
	SERVER_MAX_OBJECT_SIZE_IN_MEM,
	SERVER_MAXFDS,
	CACHE_DIR,
	TIMEOUT_CLIENT_LIFE,
	TIMEOUT_SERVER_LIFE,
	TIMEOUT_REQUEST,
	TIMEOUT_REPLY,
	TIMEOUT_CONNECT,
};
typedef struct {
	int id;
	const char *key;
}ini_key_t;

static const ini_key_t ini_keys[] ={
	{SERVER_NONE, "server:none"},
	{SERVER_PORT, "server:port"}, 
	{SERVER_BIND_ADDR4, "server:bind_addr4"},
	{SERVER_MAX_SIZE_IN_SHM, "server:max_size_in_shm"},
	{SERVER_MAX_SIZE_IN_MEM, "server:max_size_in_mem"}, 
	{SERVER_WORKER, "server:worker"},
	{SERVER_OBJECTS, "server:objects"},
	{SERVER_DEBUG_MODE, "server:debug_mode"}, 
	{SERVER_DEBUG_LEVEL, "server:debug_level"},
	{SERVER_MAX_OBJECT_SIZE_IN_MEM, "server:max_object_size_in_mem"},
	{SERVER_MAXFDS, "server:maxfds"}, 
	{CACHE_DIR, "cache:dir"},
	{TIMEOUT_CLIENT_LIFE, "timeout:client_life"},
	{TIMEOUT_SERVER_LIFE, "timeout:server_life"},
	{TIMEOUT_REQUEST, "timeout:request"},
	{TIMEOUT_REPLY, "timeout:reply"},
	{TIMEOUT_CONNECT, "timeout:connect"},
};

/* format is (type *t, int index, dictionary *d) */
static void time_parse(time_t *retv, int index, dictionary *dic);
static void size_parse(int64_t *retv, int index, dictionary *dic);
static void int_parse(int *retv, int index, dictionary *dic);
static void netaddr_parse(struct in_addr *retv, int index, dictionary *dic);
static void cache_dir_parse(array **retv, int index, dictionary *dic);

#include "conf_pre.h"

static void cache_dir_parse(array **retv, int index, dictionary *dic)
{
	if(reload_flag) 
		return;

	array *dirs = *retv;
	char *str;
	char new_str[MAX_BUFFER];
	char *token = NULL;
	char tmp[MAX_BUFFER];
	
	if((str = iniparser_getstring(dic, INI_KEY(index), NULL)) == NULL) {
		conf_debug("not find %s\n", INI_KEY(index));
		return;
	}
	strcpy(new_str, str);
	conf_debug("find %s %s\n", INI_KEY(index), str);
	token = (char *)strtok(new_str, ";");
	do {
		if(!token) 
			break;
		//conf_debug("token %s\n", token);
		strcpy(tmp, token);
		cache_dir_t *dentry = mempool_alloc(sizeof(*dentry));
		int len;
		char *pptr;
		char *token2 = (char *)strtok_r(tmp, " \t", &pptr); 

		assert(token2);
		//conf_debug("token2(path) %s\n", token2);
		dentry->path = strdup(token2);
		token2 = (char *)strtok_r(NULL, " \t", &pptr);
		assert(token2);
		//conf_debug("token2(max_size) %s\n", token2);
		dentry->max_size = atoi(token2);
		len = strlen(token2);
		switch(tolower(token2[len - 1])) {
			case 'k':
				dentry->max_size <<= 10;
				break;
			case 'm':
				dentry->max_size <<= 20;
				break;
			case 'g':
				dentry->max_size <<= 30;
				break;
			default:
				break;
		}
		dentry->no = dirs->count;
		array_append(dirs, dentry);
	}while((token = (char *)strtok(NULL, ";")));
}

static void time_parse(time_t *retv, int index, dictionary *dic)
{
	time_t inte;
	char *string;
	
	if((string = (char *)iniparser_getstring(dic, INI_KEY(index), NULL)) != NULL) {
		int len = strlen(string);
		*retv = atol(string);

		if(string[len-1] == 'm' || string[len-1] == 'M') 
			*retv *= 60;
		if(string[len-1] == 'h' || string[len-1] == 'H') 
			*retv *= 3600;
		if(string[len-1] == 'd' || string[len-1] == 'D') 
			*retv *= 86400;
		conf_debug("find %s %ld\n", INI_KEY(index), *retv);
	}
	else if((inte = iniparser_getint(dic, INI_KEY(index), -1)) != -1) {
		*retv = inte;
		conf_debug("find %s %d\n", INI_KEY(index), inte);
	}
	else {
		conf_debug("not find %s\n", INI_KEY(index));
	}
}

static void size_parse(int64_t *retv, int index, dictionary *dic)
{
	int inte;
	char *string;
	
	if((string = (char *)iniparser_getstring(dic, INI_KEY(index), NULL)) != NULL) {
		int len = strlen(string);
		*retv = atoll(string);

		if(string[len-1] == 'K' || string[len-1] == 'k') 
			*retv = *retv << 10;
		if(string[len-1] == 'M' || string[len-1] == 'm') 
			*retv = *retv << 20;
		if(string[len-1] == 'G' || string[len-1] == 'g') 
			*retv = *retv << 30;
		conf_debug("find %s %lld bytes\n", INI_KEY(index), *retv);
	}
	else if((inte = iniparser_getint(dic, INI_KEY(index), -1)) != -1) {
		*retv = inte;
		conf_debug("find %s %d\n", INI_KEY(index), inte);
	}
	else {
		conf_debug("not find %s\n", INI_KEY(index));
	}
}

static void int_parse(int *retv, int index, dictionary *dic)
{
	int inte;

	if((inte = iniparser_getint(dic, INI_KEY(index), -1)) != -1) {
		*retv = inte;
		conf_debug("find %s %d\n", INI_KEY(index), inte);
	}
	else {
		conf_debug("not find %s\n", INI_KEY(index));
	}
}

static void netaddr_parse(struct in_addr *retv, int index, dictionary *dic)
{
	char * str;
	
	if((str = iniparser_getstring(dic, INI_KEY(index), NULL)) != NULL) {
		inet_pton(AF_INET, str, retv);
		conf_debug("find %s %s\n", INI_KEY(index), str);
	}
	else 
		conf_debug("not find %s\n", INI_KEY(index));
}

void parse_ini_conf(const char *ini_conf)
{
	autogen_ini_parse(ini_conf);
}
#else 
#define MIN_EXTRA 20
static void lua_conf_server_parse(lua_State *l);
static void lua_conf_timeout_parse(lua_State *l);
static void lua_conf_cache_dir_parse(lua_State *l);
static void cache_dir_add(array *dir, lua_State *l);
static void lua_stack_view(lua_State *l);

void parse_lua_conf(const char *lua_conf)
{
	if(!lua_conf) {
		fprintf(stderr, "%s::%d lua conf is null. DEFAULT SETTINGS.\n",__FILE__, __LINE__);
		return;
	}
	
	lua_State *l = (lua_State *)luaL_newstate();
	if(!l) {
		fprintf(stderr, "%s::%d parse_lua_conf failed ", __FILE__, __LINE__);
		lua_error(l);
	}
	
	luaopen_base(l);
	luaopen_table(l);
	luaopen_string(l);

	//lua_stack_view(l);
	/* check stack */
	lua_checkstack(l, MIN_EXTRA);
	/* load lua conf */
	if(luaL_dofile(l, lua_conf) == 1) {
		fprintf(stderr, "%s::%d parse_lua_conf failed to execute luaL_dofile %s\n", \
						__FILE__, __LINE__, lua_conf);
		lua_error(l);
		abort();
	}
	else 
		fprintf(stderr, "%s::%d parse_lua_conf success to execute luaL_dofile %s\n", \
						__FILE__, __LINE__, lua_conf);
	
   	lua_conf_server_parse(l);
	lua_conf_timeout_parse(l);
	lua_conf_cache_dir_parse(l);
	
	lua_close(l);
}

static void lua_conf_server_parse(lua_State *l)
{
	assert(l);

	lua_getglobal(l, "server"); /* remaid to pop */
	if(lua_isnil(l, -1)) {
		fprintf(stderr, "%s::%d parse server failed, return nil\n", __FILE__, __LINE__);
		lua_pop(l, 1);
		return;
	}

	if(!lua_istable(l, -1)) {
		fprintf(stderr, "%s::%d parse server failed ", __FILE__, __LINE__);
		lua_error(l);
		return;
	}
	/* parse server.port */
	lua_getfield(l, -1, "port");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(!lua_isnumber(l, -1)) {
		fprintf(stderr, "%s::%d parse server.port failed", __FILE__, __LINE__);
		lua_error(l);
	}
	else {
		int port = (int)lua_tointeger(l, -1);
		conf->server.port = htons(port);
		fprintf(stderr, "%s::%d server.port =  %d\n", __FILE__, __LINE__, conf->server.port);
	}
	lua_pop(l, 1);

	/* parse server.bind_addr4 */
	lua_getfield(l, -1, "bind_addr4");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(!lua_isstring(l, -1)) {
		fprintf(stderr, "%s::%d parse server.bind_addr4 failed", __FILE__, __LINE__);
		lua_error(l);
	}
	else {
		char *addr = (char *)lua_tostring(l, -1);
		inet_pton(AF_INET, addr, &conf->server.bind_addr4);
		fprintf(stderr, "%s::%d server.bind_addr4 =  %s\n", __FILE__, __LINE__, addr);
	}
	lua_pop(l, 1);

	/* parse server.max_size_in_shm */
	lua_getfield(l, -1, "max_size_in_shm");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_size_parse((long long *)&conf->server.max_size_in_shm, value);
		fprintf(stderr, "%s::%d server.max_size_in_shm = %lld\n",\
					   	__FILE__, __LINE__, conf->server.max_size_in_shm);
	}
	else if(lua_isnumber(l, -1)) {
		conf->server.max_size_in_shm = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.max_size_in_shm =  %lld\n",\
					   	__FILE__, __LINE__, conf->server.max_size_in_shm);
	}
	else {
		fprintf(stderr, "%s::%d parse server.max_size_in_shm failed", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* parse server.max_size_in_mem */
	lua_getfield(l, -1, "max_size_in_mem");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_size_parse((long long *)&conf->server.max_size_in_mem, value);
		fprintf(stderr, "%s::%d server.max_size_in_mem =  %lld\n",\
					   	__FILE__, __LINE__, conf->server.max_size_in_mem);
	}
	else if(lua_isnumber(l, -1)) {
		conf->server.max_size_in_mem = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.max_size_in_shm =  %lld\n",\
					   	__FILE__, __LINE__, conf->server.max_size_in_mem);
	}
	else {
		fprintf(stderr, "%s::%d parse server.max_size_in_mem failed", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* parse server.worker */
	lua_getfield(l, -1, "worker");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->server.worker = (int)lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.worker =  %d\n",\
					   	__FILE__, __LINE__, conf->server.worker);
	}
	else {
		fprintf(stderr, "%s::%d parse server.worker failed", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);
	
	/* parse server.objects */
	lua_getfield(l, -1, "objects");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->server.objects = (long long)lua_tonumber(l, -1);
		fprintf(stderr, "%s::%d server.objects =  %lld\n",\
					   	__FILE__, __LINE__, conf->server.objects);
	}
	else {
		fprintf(stderr, "%s::%d parse server.objects failed", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* parse server.debug_mode */
	lua_getfield(l, -1, "debug_mode");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->server.debug_mode = (int)lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.debug_mode =  %d\n",\
					   	__FILE__, __LINE__, conf->server.debug_mode);
	}
	else {
		fprintf(stderr, "%s::%d parse server.debug_mode failed", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* parse server.debug_level */
	lua_getfield(l, -1, "debug_level");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->server.debug_level = (int)lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.debug_level =  %d\n",\
					   	__FILE__, __LINE__, conf->server.debug_level);
	}
	else {
		fprintf(stderr, "%s::%d parse server.debug_level failed", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* parse server.max_object_size_in_mem */
	lua_getfield(l, -1, "max_object_size_in_mem");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_size_parse((long long *)&conf->server.max_object_size_in_mem, value);
		fprintf(stderr, "%s::%d server.max_object_size_in_memm = %lld\n",\
					   	__FILE__, __LINE__, conf->server.max_object_size_in_mem);
	}
	else if(lua_isnumber(l, -1)) {
		conf->server.max_object_size_in_mem = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.max_object_size_in_mem =  %lld\n",\
					   	__FILE__, __LINE__, conf->server.max_object_size_in_mem);
	}
	else {
		fprintf(stderr, "%s::%d parse server.max_object_size_in_mem failed\n", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* parse server.maxfds */
	lua_getfield(l, -1, "maxfds");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->server.maxfds = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d server.maxfds =  %d\n",\
					   	__FILE__, __LINE__, conf->server.maxfds);
	}
	else {
		fprintf(stderr, "%s::%d parse server.maxfds failed\n", __FILE__, __LINE__);
		lua_error(l);
	}
	lua_pop(l, 1);

	/* pop server table */
	lua_pop(l, 1);
}



static void lua_conf_timeout_parse(lua_State *l)
{
	assert(l);

	lua_getglobal(l, "timeout"); /* remaid to pop */
	if(lua_isnil(l, -1)) {
		fprintf(stderr, "%s::%d parse timeout failed, return nil\n", __FILE__, __LINE__);
		lua_pop(l, 1);
		return;
	}

	if(!lua_istable(l, -1)) {
		fprintf(stderr, "%s::%d parse timeout failed", __FILE__, __LINE__);
		lua_error(l);
	}

	/* parse timeout.request */
	lua_getfield(l, -1, "request");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->timeout.request = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d timeout.request = %ld\n", __FILE__, __LINE__,  conf->timeout.request);
	}
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_time_parse(&conf->timeout.request, value);
		fprintf(stderr, "%s::%d timeout.request = %d\n", __FILE__, __LINE__, conf->timeout.request);
	}
	else {
		fprintf(stderr, "%s::%d timeout.request failed\n", __FILE__, __LINE__);
	}
	lua_pop(l, 1);


	/* parse timeout.reply */
	lua_getfield(l, -1, "reply");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->timeout.reply = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d timeout.reply = %d\n", __FILE__, __LINE__, conf->timeout.reply);
	}
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_time_parse(&conf->timeout.reply, value);
		fprintf(stderr, "%s::%d timeout.reply = %d\n", __FILE__, __LINE__, conf->timeout.reply);
	}
	else {
		fprintf(stderr, "%s::%d timeout.reply failed\n", __FILE__, __LINE__);
	}
	lua_pop(l, 1);

	/* parse timeout.connect */
	lua_getfield(l, -1, "connect");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->timeout.connect = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d timeout.connect = %d\n", __FILE__, __LINE__, conf->timeout.connect);
	}
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_time_parse(&conf->timeout.connect, value);
		fprintf(stderr, "%s::%d timeout.connect = %d\n", __FILE__, __LINE__,  conf->timeout.connect);
	}
	else {
		fprintf(stderr, "%s::%d timeout.connect failed\n", __FILE__, __LINE__);
	}
	lua_pop(l, 1);


	/* parse timeout.client_life */
	lua_getfield(l, -1, "client_life");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->timeout.client_life = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d timeout.client_life = %d\n", __FILE__, __LINE__, conf->timeout.client_life);
	}
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_time_parse(&conf->timeout.client_life, value);
		fprintf(stderr, "%s::%d timeout.client_life = %d\n", __FILE__, __LINE__, conf->timeout.client_life);
	}
	else {
		fprintf(stderr, "%s::%d timeout.client_life failed\n", __FILE__, __LINE__);
	}
	lua_pop(l, 1);


	/* parse timeout.server_life */
	lua_getfield(l, -1, "server_life");
	if(lua_isnil(l, -1)) 
		(void *) 0;
	else if(lua_isnumber(l, -1)) {
		conf->timeout.server_life = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d timeout.server_life = %d\n", __FILE__, __LINE__, conf->timeout.server_life);
	}
	else if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_time_parse(&conf->timeout.server_life, value);
		fprintf(stderr, "%s::%d timeout.server_life = %d\n", __FILE__, __LINE__, conf->timeout.server_life);
	}
	else {
		fprintf(stderr, "%s::%d timeout.server_life failed\n", __FILE__, __LINE__);
	}
	lua_pop(l, 1);
	
	/* pop timeout */
	lua_pop(l, 1);
}

static void lua_conf_cache_dir_parse(lua_State *l)
{
	assert(l);

	lua_getglobal(l, "cache_dir");
	if(lua_isnil(l, -1)) {
		fprintf(stderr, "%s::%d parse cache_dir failed, return nil\n", __FILE__, __LINE__);
		lua_pop(l, 1);
		return;
	}
	
	if(!lua_istable(l, -1)) {
		fprintf(stderr, "%s::%d parse cache_dir failed", __FILE__, __LINE__);
		lua_error(l);
	}
	
	if(conf->cache_dir) {
		int i;
		for(i = 0; i < conf->cache_dir->count; i++) {
			cache_dir_t *cd = conf->cache_dir->items[i];
			mempool_free(cd);
		}
		array_clean(conf->cache_dir);
	}

	lua_pushnil(l);  /* the first key */
	while (lua_next(l, -2) != 0) {
		if(lua_istable(l, -1)) 
			cache_dir_add(conf->cache_dir, l);
		/* remove value */
		lua_pop(l, 1);
	}

	lua_pop(l, 1);
}

static void cache_dir_add(array *dir, lua_State *l)
{
	if(!dir) {
		fprintf(stderr, "%s::%d dir is null\n", \
						__FILE__, __LINE__);
		
		return;
	}

	if(!l) 
		return;

	cache_dir_t *dentry = mempool_alloc(sizeof(*dentry));
	assert(dentry);
	
	lua_getfield(l, -1, "path");
	if(lua_isstring(l, -1)) {
		dentry->path = strdup((char *)lua_tostring(l, -1));
		fprintf(stderr, "%s::%d cache_dir[].path = %s\n", \
						__FILE__, __LINE__, dentry->path);
	}
	else {
		fprintf(stderr, "%s::%d cache_dir[].path get failed\n", \
						__FILE__, __LINE__);
	}
	lua_pop(l, 1);
	
	/* parse max_size */	
	lua_getfield(l, -1, "max_size");
	if(lua_isstring(l, -1)) {
		char *value = (char *)lua_tostring(l, -1);
		lua_size_parse(&dentry->max_size, value);
		fprintf(stderr, "%s::%d cache_dir[].max_size = %lld\n", \
						__FILE__, __LINE__, dentry->max_size);
	}
	else if(lua_isnumber(l, -1)) {
		dentry->max_size = lua_tointeger(l, -1);
		fprintf(stderr, "%s::%d cache_dir[].max_size = %lld\n", \
						__FILE__, __LINE__, dentry->max_size);
	}
	else {
		fprintf(stderr, "%s::%d cache_dir[].max_size get failed\n", \
						__FILE__, __LINE__);
	}
	lua_pop(l, 1);

	array_append(dir, dentry);
}


static void lua_stack_view(lua_State *l)
{
	int i;
	int top;
	top = lua_gettop(l);
	
	fprintf(stderr, "stack count %d\n", top);

	for(i = 1; i <= top; i++) {
		fprintf(stderr, "[%d] %s\n", i, lua_typename(l, lua_type(l, -1)));
	}
	fprintf(stderr, "\n");
}
#endif
